/*******************************************************************************
 * FilePath    : \Software\Examples\Ble\ble_app_peripheral_AirSync\Src\BSP\UART.c
 * Version     : 1.0
 * Brief       : 
 * Author      : AndrewHu
 * Company     : Shanghai MacroGiga Electronics CO.,Ltd
 * Email       : Hubinbo@macrogiga.com
 * Date        : 2020-04-03 15:06:14
 * LastEditors : AndrewHu
 * LastEditTime: 2021-04-21 18:07:18
 * Description : 
 ******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <Includes.h>
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define MAX_SIZE 200
#define AT_CMD_MAX 100
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

u32 BaudRate = BaudRate_Def;
static u8 txBuf[MAX_SIZE], rxBuf[MAX_SIZE];
static u8 txCount = 0, rxCount = 0; //待发送、接收待取出数据的Index
static u8 txLen = 0, rxLen = 0;     //已发送、接收并取出数据的Index
static u8 rxTimeOut = 0;            //接收超时，判断串口数据是否发送完成
static u8 txEn = 0;                 //发送使能标志
/* Private function ----------------------------------------------------------*/
/* extern --------------------------------------------------------------------*/

/*******************************************************************************
 * Function    : UartInit
 * Brief       : 
 * Parameter   : {u32} baudRate-波特率
 * Returns     : 
 * Date        : 2020-04-03 16:53:11
 * Description : 
 ******************************************************************************/
void UartInit(u32 baudRate)
{
    UART_InitTypeDef UART_InitStructure;

    //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_UART1, ENABLE); //使能UART1，GPIOA时钟

    //UART1 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = UART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 3; //优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);                 //根据指定的参数初始化VIC寄存器

    //UART 初始化设置
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);

    UART_InitStructure.UART_BaudRate = baudRate;                                 //串口波特率
    UART_InitStructure.UART_WordLength = UART_WordLength_8b;                     //字长为8位数据格式
    UART_InitStructure.UART_StopBits = UART_StopBits_1;                          //一个停止位
    UART_InitStructure.UART_Parity = UART_Parity_No;                             //无奇偶校验位
    UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None; //无硬件数据流控制
    UART_InitStructure.UART_Mode = UART_Mode_Rx | UART_Mode_Tx;                  //收发模式

    UART_Init(UART1, &UART_InitStructure);       //初始化串口1
    UART_ITConfig(UART1, UART_IT_RXIEN, ENABLE); //开启串口接受中断
    UART_ITConfig(UART1, UART_IT_TXIEN, DISABLE);
    UART_Cmd(UART1, ENABLE); //使能串口1

    //UART1_TX   GPIOA.9
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
    GPIO_Init(GPIOA, &GPIO_InitStructure);          //初始化GPIOA.9

    //UART1_RX	  GPIOA.10初始化
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;            //PA10
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);                //初始化GPIOA.10
}
/*******************************************************************************
 * Function    : ChangeBaudRate
 * Brief       : 更改波特率
 * Parameter   : 
 * Returns     : 
 * Date        : 2020-04-03 16:52:30
 * Description : 
 ******************************************************************************/
void ChangeBaudRate(u32 bRate)
{
    BaudRate = bRate;
    UART_Cmd(UART1, DISABLE);
    UartInit(bRate); //初始化串口1
}
/*******************************************************************************
 * Function    : 
 * Brief       : 
 * Parameter   : 
 * Returns     : 
 * Date        : 2020-04-03 17:06:41
 * Description : 
 ******************************************************************************/
u32 GetBaudRate(void)
{
    return BaudRate;
}
/*******************************************************************************
* Function   :      UART1_IRQHandler
* Parameter  :      void
* Returns    :      void
* Description:
* Note:      :      串口1中断服务程序
*******************************************************************************/
void UartRx_Int(void)
{
    rxBuf[rxCount] = UART_ReceiveData(UART1); //保存串口接收到的值

    //比较缓存是否溢出
    rxCount++;
    if (rxCount >= MAX_SIZE)
        rxCount = 0x00;
    rxTimeOut = 0x00; //倒计时，判断串口数据是否接收完
}
/*******************************************************************************
* Function   :      UART1_IRQHandler
* Parameter  :      void
* Returns    :      void
* Description:
* Note:      :      串口1中断服务程序
*******************************************************************************/
void UartTx_Int(void)
{
    //还有数据未发完
    if (txCount != txLen)
    {
        UART_SendData(UART1, txBuf[txLen]);
        //比较缓存是否溢出
        txLen++;
        if (txLen >= MAX_SIZE)
            txLen = 0x00;
    }
    else
    {
        //数据发送完成
        UART_ITConfig(UART1, UART_IT_TXIEN, DISABLE); //关闭串口发送中断
        txEn = 0x00;
    }
}
/*******************************************************************************
* Function   :      UART1_IRQHandler
* Parameter  :      void
* Returns    :      void
* Description:
* Note:      :      串口1中断服务程序
*******************************************************************************/
void UART1_IRQHandler(void)
{
    if (UART_GetITStatus(UART1, UART_IT_RXIEN) != RESET)
    {                                                 //接收中断
        UART_ClearITPendingBit(UART1, UART_IT_RXIEN); //清串口中断
        UartRx_Int();
    }
    if (UART_GetITStatus(UART1, UART_IT_TXIEN) != RESET)
    {
        UART_ClearITPendingBit(UART1, UART_IT_TXIEN); //清发送完成中断
        UartTx_Int();
    }
}
/*******************************************************************************
 * Function    : Uart_Send_Byte
 * Brief       : 
 * Parameter   : 
 * Returns     : 
 * Date        : 2020-03-24 18:28:52
 * Description : 串口发送一个字节
 ******************************************************************************/
void Uart_Send_Byte(u8 data)
{
    txBuf[txCount] = data;
    txCount++;
    if (txCount >= MAX_SIZE)
        txCount = 0x00;
}
/*******************************************************************************
 * Function    : Uart_Send_Byte2Ascii
 * Brief       : 
 * Parameter   : {u8} data-待发送数据
 * Returns     : 
 * Date        : 2020-03-24 18:30:09
 * Description : 串口发送一个字节（转换成ASCII）
 ******************************************************************************/
void Uart_Send_Byte2Ascii(u8 data)
{
    Uart_Send_Byte(AHL_Data_Hex2Ascii_4bit(data >> 4));
    Uart_Send_Byte(AHL_Data_Hex2Ascii_4bit(data));
}
/*******************************************************************************
 * Function    : Uart_Send_Array
 * Brief       : 
 * Parameter   : {u8*} data-待发送数组
 * Parameter   : {u8} len-数组长度
 * Returns     : 
 * Date        : 2020-03-24 18:30:47
 * Description : 发送一个数组（原始数据）
 ******************************************************************************/
void Uart_Send_Array(u8 *data, u8 len)
{
    u8 i;
    for (i = 0; i < len; i++)
    {
        Uart_Send_Byte(data[i]);
    }
}
/*******************************************************************************
 * Function    : Uart_Send_Array_R
 * Brief       : 
 * Parameter   : {u8*} data-待发送数组
 * Parameter   : {u8} len-数组长度
 * Returns     : 
 * Date        : 2020-03-24 18:30:47
 * Description : 发送一个数组（原始数据），倒序
 ******************************************************************************/
void Uart_Send_Array_R(u8 *data, u8 len)
{
    u8 i;
    for (i = len; i != 0; i--)
    {
        Uart_Send_Byte(data[i - 1]);
    }
}
/*******************************************************************************
 * Function    : Uart_Send_Array2Ascii
 * Brief       : 
 * Parameter   : {u8*} data-待发送数组
 * Parameter   : {u8} len-数组长度
 * Parameter   : {u8} space-是否空格做间隔
 * Returns     : 
 * Date        : 2020-03-24 18:30:47
 * Description : 发送一个数组（转成ASCII）
 ******************************************************************************/
void Uart_Send_Array2Ascii(u8 *data, u8 len, u8 space)
{
    u8 i;
    for (i = 0; i < len; i++)
    {
        Uart_Send_Byte2Ascii(data[i]);
        if (space)
            Uart_Send_Byte(' '); //插入空格
    }
}
/*******************************************************************************
 * Function    : Uart_Send_Array2Ascii_R
 * Brief       : 
 * Parameter   : {u8*} data-待发送数组
 * Parameter   : {u8} len-待发送数组长度
 * Parameter   : {u8} space-是否空格做间隔
 * Returns     : 
 * Date        : 2020-03-24 18:30:47
 * Description : 发送一个数组（转成ASCII），倒序
 ******************************************************************************/
void Uart_Send_Array2Ascii_R(u8 *data, u8 len, u8 space)
{
    u8 i;
    for (i = len; i != 0; i--)
    {
        Uart_Send_Byte2Ascii(data[i - 1]);
        if (space)
            Uart_Send_Byte(' '); //插入空格
    }
}
/*******************************************************************************
 * Function    : Uart_Send_String
 * Brief       : 
 * Parameter   : {u8*} data-字符串或数组
 * Returns     : {u8} len-长度
 * Date        : 2020-03-24 18:48:47
 * Description : 发送一个字符串或数组
 ******************************************************************************/
void Uart_Send_String(u8 *data, u8 len)
{
    u8 i;
    for (i = 0; i < len; i++)
    {
        txBuf[txCount] = *(data + i);
        txCount++;
        if (txCount >= MAX_SIZE)
            txCount = 0x00;
    }
}
/*******************************************************************************
 * Function    : GetUartTxFlag
 * Brief       : 
 * Parameter   : 
 * Returns     : 
 * Date        : 2020-03-25 15:16:44
 * Description : 获取串口发送状态
 ******************************************************************************/
u8 GetUartTxFlag(void)
{
    return txEn;
}
/*******************************************************************************
 * Function    : GetUartStatus
 * Brief       : 获取串口工作状态
 * Parameter   : 
 * Returns     : 
 * Date        : 2020-03-25 15:16:44
 * Description : 
 ******************************************************************************/
u8 GetUartStatus(void)
{
    if ((txEn != 0) || (txLen != txCount) || (rxLen != rxCount))
        return 1; //串口有数据待处理
    else
        return 0; //串口空闲
}
/*******************************************************************************
 * Function    : BleSendData
 * Brief       : 
 * Parameter   : {u8} overflag-串口数据是否接收完成
 * Returns     : 
 * Date        : 2020-03-23 17:36:40
 * Description : 从串口接受数组中取出数据给蓝牙发送
 ******************************************************************************/
static void BleSendData(u8 overflag)
{
    u8 i = 0;
    u8 bleUartData[20] = {0};

    if (overflag == 0)
    {
        //数据尚未接收完
        if (rxCount >= rxLen)
        {
            if ((rxCount - rxLen) < 20)
                return; //没有达到20个字节
        }
        else
        {
            if ((MAX_SIZE - rxLen + rxCount) < 20)
                return; //没有达到20个字节
        }
    }
    //达到了20个字节，或接收完成
    while (rxCount != rxLen) //有待取出数据
    {
        bleUartData[i] = rxBuf[rxLen];
        rxLen++;
        if (rxLen >= MAX_SIZE)
            rxLen = 0;
        i++;
        if (i >= 20)
            break; //数据长度超过20，只发送20个字节
    }

    if (GetConnectedStatus())
    {
        SendNotifyData(bleUartData, i);
        Printf_OK();
    }
    else
    {
        //蓝牙未连接
        Printf_ConnectStatus(0);
    }
}
/*******************************************************************************
 * Function    : Uart_Send_Data
 * Brief       : 
 * Parameter   : 
 * Returns     : 
 * Date        : 2020-03-24 19:02:59
 * Description : 串口数据发送判断
 ******************************************************************************/
void Uart_Send_Data(void)
{
    if ((txLen != txCount) && (txEn == 0))
    {
        //有数据待发送，发送使能标志未置1
        //Exit2Uart();
        txEn = 1;
        UART_ITConfig(UART1, UART_IT_TXIEN, ENABLE);
        UART_SendData(UART1, txBuf[txLen]);
    }
}
/*******************************************************************************
 * Function    : Uart_Receive_Data
 * Brief       : 
 * Parameter   : 
 * Returns     : 
 * Date        : 2020-03-24 19:01:52
 * Description : 接收数据
 ******************************************************************************/
void Uart_Receive_Data(void)
{
    if (rxLen == rxCount)
    {
        rxTimeOut = 0x00;
        return; //没有接收到数据
    }

    if (rxTimeOut < 0x02) //
    {
        //串口正在接受数据
        rxTimeOut++; //串口有数据时会一直清零

        //透传模式，接收到的数据超过20个字节，取出数据
        BleSendData(0);
    }
    else
    {
        //串口数据接收完成，取出数据

        BleSendData(1);
        rxTimeOut = 0x00;
    }
}
/*******************************************************************************
 * Function    : Fun_Uart_Run
 * Brief       : 
 * Parameter   : 
 * Returns     : 
 * Date        : 2020-03-24 19:02:19
 * Description : 串口执行
 ******************************************************************************/
void Fun_Uart_Run(void)
{
    Uart_Send_Data();
    Uart_Receive_Data();
}
